package chenji.gunapi.pluginmessage;

import java.util.TreeSet;

import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;

import chenji.gunapi.Main;
import chenji.gunapi.pluginmessage.event.ExceptionPrinter;
import chenji.gunapi.pluginmessage.event.GunAPIPackageReceiveEvent;
import chenji.gunapi.pluginmessage.event.GunAPIPackageSendEvent;
import chenji.gunapi.pluginmessage.event.PackageListener;
import chenji.gunapi.pluginmessage.packages.InMousePackage;
import chenji.gunapi.pluginmessage.packages.InVerifyPackage;
import chenji.gunapi.pluginmessage.packages.OutVerifyPackage;
import chenji.gunapi.pluginmessage.packages.UnknownPackage;

public class PackageManager {
	private OutGunAPIPackage verifypackage = new OutVerifyPackage();
	private TreeSet<PackageListener> tree = new TreeSet<>();

	public void sendPackage(Player p, OutGunAPIPackage pack) {
		GunAPIPackageSendEvent e = new GunAPIPackageSendEvent(p, pack);
		this.callevent(e);
		if (e.isCancelled()) {
			return;
		}
		p.sendPluginMessage(Main.getPlugin(), PluginMessageUntl.getPluginMessageUntl().getChannel(), e.getPackage().getByte());
	}

	public void receiveData(Player p, byte[] data) {
		ByteArrayDataInput o = ByteStreams.newDataInput(data);
		int i = o.readInt();
		if (i == 0) {
			this.callevent(new GunAPIPackageReceiveEvent(new UnknownPackage(data, p)));
			return;
		}
		InGunAPIPackage pack = this.getInGunAPIPackage(p, data, i);
		this.callevent(new GunAPIPackageReceiveEvent(pack));
	}

	public InGunAPIPackage getInGunAPIPackage(Player p, byte[] data, int type) {
		switch (type) {
		case 1:
			return new InVerifyPackage(p, data);
		case 2:
			return new InMousePackage(data, p);
		}

		return new UnknownPackage(data, p, type);
	}

	public void registerPackageListener(PackageListener pl, Plugin p) {
		pl.setPlugin(p);

		if (pl.getPriority() == null) {
			ExceptionPrinter.printNullPriority(p);
		}
		this.tree.add(pl);
	}

	public void callevent(GunAPIPackageReceiveEvent e) {
		for (PackageListener l : this.tree) {
			l.onPackageReceive(e);
		}

	}

	public void callevent(GunAPIPackageSendEvent e) {
		for (PackageListener l : this.tree) {
			l.onPackageSend(e);
		}
	}

	public void sendVerfiyPackage(Player p) {
		this.sendPackage(p, this.verifypackage);
	}

}
